package com.financial.service.heemoney.utils;


import org.apache.tomcat.util.codec.binary.Base64;
import org.springframework.core.io.ClassPathResource;

import java.io.InputStream;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
import java.util.*;

/**
 * 签名验签工具
 * 
 * @author chang
 *
 */

public class SignUtils {

	// 缓存公钥和私钥
	public static Map<String, Object> certMap = new java.util.concurrent.ConcurrentHashMap<String, Object>();

	/**
	 * 除去数组中的空值和签名参数
	 * 
	 * @param sArray
	 *            签名参数组
	 * @return 去掉空值与签名参数后的新签名参数组
	 */
	public static Map<String, String> paraFilter(Map<String, String> sArray) {

		Map<String, String> result = new HashMap<String, String>();

		if (sArray != null && sArray.size() > 0) {
			for (String key : sArray.keySet()) {
				String value = sArray.get(key);
				System.out.println(key+"="+value);
				if (value == null || YsStringUtils.isEmpty(value) || key.equalsIgnoreCase("sign")) {
					continue;
				}
				result.put(key, value);
			}
		}
		return result;
	}

	/**
	 * 遍历以及根据重新排序
	 * 
	 * @param sortedParams
	 * @return
	 */
	public static String getSignContent(Map<String, String> sortedParams) {
		StringBuffer content = new StringBuffer();
		List<String> keys = new ArrayList<String>(sortedParams.keySet());
		Collections.sort(keys);
		int index = 0;
		for (int i = 0; i < keys.size(); i++) {
			String key = keys.get(i);
			String value = sortedParams.get(key);
			if (YsStringUtils.areNotEmpty(key, value)) {
				content.append((index == 0 ? "" : "&") + key + "=" + value).append("key").append("=").append(key);
				index++;
			}
		}
		return content.toString();
	}






	/**
	 * 读取公钥，x509格式
	 * @param ins
	 * @return
	 * @throws Exception
	 * @see
	 */
	public static PublicKey getPublicKeyFromCert(InputStream ins) throws Exception {
		PublicKey pubKey = (PublicKey) certMap.get("PublicKey");
		if (pubKey != null) {
			return pubKey;
		}

		try {
			CertificateFactory cf = CertificateFactory.getInstance("X.509");
			Certificate cac = cf.generateCertificate(ins);
			pubKey = cac.getPublicKey();
			certMap.put("PublicKey", pubKey);
		} catch (Exception e) {
			if (ins != null)
				ins.close();
			throw e;
		} finally {
			if (ins != null) {
				ins.close();
			}
		}

		return pubKey;
	}

	/**
	 * 读取PKCS12格式的key（私钥）pfx格式
	 * 
	 * @param password
	 * @param ins
	 * @return
	 * @throws Exception
	 * @see
	 */
	public static PrivateKey getPrivateKeyFromPKCS12(String password, InputStream ins) throws Exception {
		PrivateKey priKey = (PrivateKey) certMap.get("PrivateKey");
		if (priKey != null) {
			return priKey;
		}

		KeyStore keystoreCA = KeyStore.getInstance("PKCS12");
		try {
			// 读取CA根证书
			keystoreCA.load(ins, password.toCharArray());

			Enumeration<?> aliases = keystoreCA.aliases();
			String keyAlias = null;
			if (aliases != null) {
				while (aliases.hasMoreElements()) {
					keyAlias = (String) aliases.nextElement();
					// 获取CA私钥
					priKey = (PrivateKey) (keystoreCA.getKey(keyAlias, password.toCharArray()));
					if (priKey != null) {
						certMap.put("PrivateKey", priKey);
						break;
					}
				}
			}
		} catch (Exception e) {
			if (ins != null)
				ins.close();
			e.printStackTrace();
			throw e;
		} finally {
			if (ins != null) {
				ins.close();
			}
		}

		return priKey;
	}
	
	/**
	 * 读取PKCS12格式的key（私钥）pfx格式
	 * 
	 * @param password
	 * @param ins
	 * @return
	 * @throws Exception
	 * @see
	 */
	public static PrivateKey getPrivateKeyFromPKCS12DF(String password, InputStream ins) throws Exception {
		PrivateKey priKey = (PrivateKey) certMap.get("PrivateKeyDF");
		if (priKey != null) {
			return priKey;
		}
		
		try {
			KeyStore keystoreCA = KeyStore.getInstance("PKCS12");
			// 读取CA根证书
			keystoreCA.load(ins, password.toCharArray());
			
			Enumeration<?> aliases = keystoreCA.aliases();
			String keyAlias = null;
			if (aliases != null) {
				while (aliases.hasMoreElements()) {
					keyAlias = (String) aliases.nextElement();
					// 获取CA私钥
					priKey = (PrivateKey) (keystoreCA.getKey(keyAlias, password.toCharArray()));
					if (priKey != null) {
						certMap.put("PrivateKeyDF", priKey);
						break;
					}
				}
			}
		} catch (Exception e) {
			if (ins != null)
				ins.close();
			throw e;
		} finally {
			if (ins != null) {
				ins.close();
			}
		}
		
		return priKey;
	}
	
	/**
	 * 签名map参数排序
	 * @param sortedParams
	 * @return
	 */
	public static String getSContent(Map<String, Object> sortedParams) {
		Map<String, String> map = new HashMap<String, String>();
		List<String> keys = new ArrayList<String>(sortedParams.keySet());
		Collections.sort(keys);
		for (int i = 0; i < keys.size(); i++) {
			String key = keys.get(i);
			String value = sortedParams.get(key).toString();
			map.put(key, value);
		}
		return map.toString();
	}
	//异步信息验签
	public static boolean verifySign(String params) {
        Map<String, Object> changeMap = JsonUtils.jsonToMap(params);
        String sign = "";
		if (changeMap.get("sign") != null) {
			sign = changeMap.get("sign").toString();
            changeMap.remove("sign");
			SignUtils.getSContent(changeMap);
		}
		boolean isSign = false;
		try {
			isSign = params.equals(MD5Utils.MD5en(params));
		} catch (Exception e) {
			e.printStackTrace();
			throw new RuntimeException("验证签名失败");
		}
		return isSign;
	}
}
